//Polytope.cpp
//implement the polytope building procedure
//
//

#include "polytope/Polytope.h"
#include "polytope/Space.h"
using namespace std;
using namespace polytope;
using namespace crossbit;

Polytope::Polytope()
{
	one_dim_space=NULL;
	two_dim_space=NULL;
	three_dim_space=NULL;
}

Polytope::~Polytope()
{
}



int Polytope::Build_Polytope(VBlock *vb,CFG *cfg_builder,int dimension,int length)
{
	int head_position=vb->Get_In_CFG();
	this->one_dim_space=new Space_1D(dimension,length);
	int n = cfg_builder->CFG_Store[head_position].path_num;

	int next_pos=cfg_builder->CFG_Store[head_position].next_block[n-1];
	int k=0;	
	int flag=0;

	vector<int> path_vec;

	cout<<"start	"<<endl;
	for (int i = head_position; next_pos!=head_position/*cfg_builder->CFG_Store[next_pos].source_id!=head_position */;i = next_pos)
	{
		n=cfg_builder->CFG_Store[i].path_num;
		
		if (n == 1)
		{
			next_pos = cfg_builder->CFG_Store[i].next_block[0];
			path_vec.push_back(next_pos);
			cout<<next_pos<<endl;
			VBlock *p = cfg_builder->CFG_Store[next_pos].vb;
			cout<<p->Get_VBlock_ID()<<endl;
			this->one_dim_space->ops_store.push_back(*p);
			k = this->one_dim_space->ops_store.size()-1;
			cout<<"CFG:	"<<this->one_dim_space->ops_store[k].Get_VBlock_ID()<<endl;
			cout<<"Correct:	"<<cfg_builder->CFG_Store[next_pos].vb->Get_VBlock_ID()<<endl;
		}
		else
		{
			if (n == 2)
			{
				for (int path_idx = 0; path_idx < path_vec.size(); path_idx++)
				{
					if (path_vec[path_idx] == cfg_builder->CFG_Store[i].next_block[0])
					flag = 1;
				}
				

			}
			if ( flag==1 )
			{
				next_pos = cfg_builder->CFG_Store[i].next_block[1];
				
			}
			else
			{
				if (flag == 0)
				{
					next_pos = cfg_builder->CFG_Store[i].next_block[0];

				}
			}
			path_vec.push_back(next_pos);
			cout<<next_pos<<endl;

			this->one_dim_space->ops_store.push_back(*(cfg_builder->CFG_Store[next_pos].vb));
		}
	}//assign the instructions
	cout<<"end"<<endl;


	//here we start to put the points in the space, 
	//
	//Hi,Brother Sao, I'm waiting to your filter,haha
/*	Poly_Operation *poly_op;
	for (int i=0;i<this->one_dim_space->Get_1D_Size();i++)
	{
		poly_op=new Poly_Operation();
		poly_op->Set_Idx(i,0,0);
		poly_op->Mem_Op_Analysis();

		this->one_dim_space->Statements_list.push_back(*poly_op);
	
		this->one_dim_space->Dependence_Polytope(*poly_op);

	}
*/
	cout<<this->one_dim_space->ops_store.size()<<endl;
	cout<<"current statement are blocks:	"<<endl;
	for (int i=0; i < this->one_dim_space->ops_store.size(); i++)
	{
		cout<<i<<":	"<<this->one_dim_space->ops_store[i].Get_VBlock_ID()<<endl;
		
	}
	return 1;
}


#ifdef FINISH
int Polytope::Build_Polytope(VBlock *vb,CFG *cfg_builder,int dimension, int length_x, int length_y)
{
//	VBlock *p=vb;
	int head_position=vb->Get_In_CFG();
//	CFG::CFG_Node * start_node = CFG
	this->two_dim_space=new Space_2D(dimension,length_x,length_y);

	int n=cfg_builder->CFG_Store[head_position].path_num;

	int 	next_pos=cfg_builder->CFG_Store[head_position].next_block[n-1];

	int flag=0;
	vector <int> path_vec;
	for (int i = head_position; next_pos!=head_position/*cfg_builder->CFG_Store[next_pos].source_id!=head_position */;i = next_pos)
	{
		this->one_dim_space->ops_store.push_back(*(cfg_builder->CFG_Store[i].vb));
		n=cfg_builder->CFG_Store[i].path_num;
		
		//cout<<next_pos<<endl;
	//	cout<<cfg_builder->CFG_Store[i].next_block[0]<<endl;
		if (n == 1)
		{
			next_pos = cfg_builder->CFG_Store[i].next_block[0];
			path_vec.push_back(next_pos);
			cout<<next_pos<<endl;
		}
		else
		{
			if (n == 2)
			{
				for (int path_idx = 0; path_idx < path_vec.size(); path_idx++)
				{
					if (path_vec[path_idx] == cfg_builder->CFG_Store[i].next_block[0])
					flag = 1;
				}

			}
			if ( flag==1 )
			{
				next_pos = cfg_builder->CFG_Store[i].next_block[1];
				
			}
			else
			{
				if (flag == 0)
				{
					next_pos = cfg_builder->CFG_Store[i].next_block[0];

				}
			}
			path_vec.push_back(next_pos);
			
		//	cout<<next_pos<<endl;


		}


//		next_pos=cfg_builder->CFG_Store[i].next_block[n-1];
	}//assign the instructions
/*	for (int i = head_position;cfg_builder->CFG_Store[next_pos].source_id!=head_position ;i = cfg_builder->CFG_Store[i].next_block[n-1])
	{
		this->two_dim_space->ops_store.push_back(*(cfg_builder->CFG_Store[i].vb));
		
		n=cfg_builder->CFG_Store[i].path_num;

		next_pos=cfg_builder->CFG_Store[i].next_block[n-1];
	}//assign the instructions
*/
	//here we start to put the points in the space, 
	//
	//Hi,Brother Sao, I'm waiting to your filter,haha
	Poly_Operation *poly_op;
	for (int i=0;i<this->two_dim_space->Get_2D_Size().x;i++)
	  for (int j=0;j<this->two_dim_space->Get_2D_Size().y;j++)
	{
		poly_op=new Poly_Operation();
		poly_op->Set_Idx(i,j,0);
		poly_op->Mem_Op_Analysis();

		this->two_dim_space->Statements_list.push_back(*poly_op);
	
		this->two_dim_space->Dependence_Polytope(*poly_op);

	}


	return 1;
}



int Polytope::Build_Polytope(VBlock *vb,CFG *cfg_builder,int dimension, int length_x, int length_y,int length_z)
{
//	VBlock *p=vb;
	int head_position=vb->Get_In_CFG();
//	CFG::CFG_Node * start_node = CFG
	this->three_dim_space=new Space_3D(dimension,length_x,length_y,length_z);
	int n=cfg_builder->CFG_Store[head_position].path_num;
	int next_pos=cfg_builder->CFG_Store[head_position].next_block[n-1];

	int flag=0;
	vector <int> path_vec;
	for (int i = head_position; next_pos!=head_position/*cfg_builder->CFG_Store[next_pos].source_id!=head_position */;i = next_pos)
	{
		this->one_dim_space->ops_store.push_back(*(cfg_builder->CFG_Store[i].vb));
		n=cfg_builder->CFG_Store[i].path_num;
		
		//cout<<next_pos<<endl;
	//	cout<<cfg_builder->CFG_Store[i].next_block[0]<<endl;
		if (n == 1)
		{
			next_pos = cfg_builder->CFG_Store[i].next_block[0];
			path_vec.push_back(next_pos);
			cout<<next_pos<<endl;
		}
		else
		{
			if (n == 2)
			{
				for (int path_idx = 0; path_idx < path_vec.size(); path_idx++)
				{
					if (path_vec[path_idx] == cfg_builder->CFG_Store[i].next_block[0])
					flag = 1;
				}

			}
			if ( flag==1 )
			{
				next_pos = cfg_builder->CFG_Store[i].next_block[1];
				
			}
			else
			{
				if (flag == 0)
				{
					next_pos = cfg_builder->CFG_Store[i].next_block[0];

				}
			}
			path_vec.push_back(next_pos);
			
		//	cout<<next_pos<<endl;


		}


//		next_pos=cfg_builder->CFG_Store[i].next_block[n-1];
	}//assign the instructions
	/*	for (int i = head_position;cfg_builder->CFG_Store[next_pos].source_id!=head_position ;i = cfg_builder->CFG_Store[i].next_block[n-1])
	{
		this->three_dim_space->ops_store.push_back(*(cfg_builder->CFG_Store[i].vb));
		
		n=cfg_builder->CFG_Store[i].path_num;
		
		next_pos=cfg_builder->CFG_Store[i].next_block[n-1];
	}//assign the instructions
*/
	//here we start to put the points in the space, 
	//
	//Hi,Brother Sao, I'm waiting to your filter,haha
	Poly_Operation *poly_op;
	for (int i=0;i<this->three_dim_space->Get_3D_Size().x;i++)
	  for (int j=0;j<this->three_dim_space->Get_3D_Size().y;j++)
		for (int k=0;k<this->three_dim_space->Get_3D_Size().z;k++)
	{
		poly_op=new Poly_Operation();
		poly_op->Set_Idx(i,j,k);
		poly_op->Mem_Op_Analysis();

		this->three_dim_space->Statements_list.push_back(*poly_op);
	
		this->three_dim_space->Dependence_Polytope(*poly_op);

	}


	return 1;
}
#endif 
